package concept.misc;

import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.xml.DOMConfigurator;

public class LogLab
{
	static Log logger = LogFactory.getLog(LogLab.class);

	private static void log1()
	{
		Logger logger = Logger.getLogger(LogLab.class);

		RollingFileAppender debugAppender = (RollingFileAppender) Logger.getRootLogger().getAppender("DEBUG_APPENDER");
		debugAppender.setFile("C:/temp/LOG_TEST/debug.log");
		debugAppender.activateOptions();
		RollingFileAppender errorAppender = (RollingFileAppender) Logger.getRootLogger().getAppender("ERROR_APPENDER");
		errorAppender.setFile("C:/temp/LOG_TEST/error.log");
		errorAppender.activateOptions();
		RollingFileAppender infoAppender = (RollingFileAppender) Logger.getRootLogger().getAppender("INFO_APPENDER");
		infoAppender.setFile("C:/temp/LOG_TEST/info.log");
		infoAppender.activateOptions();
		RollingFileAppender warnAppender = (RollingFileAppender) Logger.getRootLogger().getAppender("WARN_APPENDER");
		warnAppender.setFile("C:/temp/LOG_TEST/warn.log");
		warnAppender.activateOptions();
		logger.debug("Debug messge via Log1");
		logger.error("Error messge via Log1");
		logger.info("Info messge via Log1");
		logger.warn("Warn messge via Log1");
	}

	private static void log2(String profile, String message)
	{
		Logger logger = Logger.getLogger(LogLab.class);

		Logger rootLogger = Logger.getRootLogger();

		RollingFileAppender fileAppender = null;
		Enumeration<Appender> appenders = rootLogger.getAllAppenders();
		while (appenders.hasMoreElements())
		{
			Appender currentAppender = (Appender) appenders.nextElement();
			if (currentAppender instanceof RollingFileAppender)
			{
				fileAppender = (RollingFileAppender) currentAppender;
				System.err.println("Got it!");
				String level = fileAppender.getThreshold().toString();
				fileAppender.setFile("C:/temp/LOG_TEST" + profile + "/" + level.toLowerCase() + "/processor_" + level + ".log");
				fileAppender.activateOptions();
				if (fileAppender != null)
				{
					logger.log(fileAppender.getThreshold(), "[" + level + "]" + message);
				}
			}
		}
	}

	private static void log3()
	{
		CustomLogger logger = (CustomLogger) Logger.getLogger(LogLab.class.getSimpleName(), new CustomLoggerFactoryImpl());
		logger.debug("This is a DEBUG message");
		logger.error("This is an ERROR message");
		logger.warn("This is a WARN message");
		logger.info("This is an INFO message");
	}

	public static void main(String[] args)
	{
		// log1();
		// log2("KansProfile", "Customised message");
		// System.setProperty("profile", "KansProfile");
		// log3();
		/*MyClass clz1 = new LogLab().new MyClass();
		MyClass clz2 = new LogLab().new MyClass();
		MyClass clz3 = new LogLab().new MyClass();
		Thread t1 = new Thread(clz1);
		Thread t2 = new Thread(clz2);
		Thread t3 = new Thread(clz3);
		t1.start();
		t2.start();
		t3.start();*/
		
		try
		{
			String.valueOf(null).length();
		}
		catch(NullPointerException e)
		{
			logger.debug(e.getMessage());
			logger.error("Simulated NPE.", e);
		}
		
	}

	
	@SuppressWarnings("unchecked")
	private static void resetFileAppender()
	{
		/*Logger rootLogger = Logger.getRootLogger();
		Enumeration<Appender> appenders = rootLogger.getAllAppenders();
		while (appenders.hasMoreElements())
		{
			Appender currentAppender = (Appender) appenders.nextElement();
			
			if (currentAppender instanceof RollingFileAppender)
			{
				FileAppender fa = (FileAppender)currentAppender;
				if(fa.getName().contains("_updated"))
				{
					rootLogger.removeAppender(fa);
				}
			}
		}*/
		//Logger rootLogger = Logger.getRootLogger();
		//rootLogger.removeAllAppenders();
		DOMConfigurator.configure("src/main/resources/log4j.xml");
	}

	@SuppressWarnings("unchecked")
	private static void updateFileAppender()
	{
		Logger rootLogger = Logger.getRootLogger();

		RollingFileAppender fileAppender = null;
		Enumeration<Appender> appenders = rootLogger.getAllAppenders();
		while (appenders.hasMoreElements())
		{
			Appender currentAppender = (Appender) appenders.nextElement();

			if (currentAppender instanceof RollingFileAppender)
			{
				fileAppender = (RollingFileAppender)currentAppender;
				//fileAppender = FileAppenderFactory.newInstance((RollingFileAppender)currentAppender);
				//rootLogger.addAppender(fileAppender);
				fileAppender.setName(currentAppender.getName()+"_updated");
				fileAppender.setFile("C:/temp/LOG_TEST/removeme-"+timestamp()+".log");
				fileAppender.setAppend(true);
				fileAppender.activateOptions();
			}
		}

	}

	private static String timestamp()
	{
		return new Date().toString().replace(" ", "-").replace(":", "-");
	}

	
	private class MyClass implements Runnable
	{
		private Logger logger = Logger.getLogger(Thread.currentThread().getName()+"->"+this.getClass());
		private MyAnotherClass clz = new MyAnotherClass();

		void log()
		{
			synchronized (logger)
			{
				logger.debug("Logged by old logger.");
				clz.log();
				LogLab.updateFileAppender();
				logger.debug("Logged by new logger");
				clz.log();
				LogLab.resetFileAppender();
				logger.debug("Logged by revised logger");
				clz.log();
			}
		}

		@Override
		public void run()
		{
			log();
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
			}
		}
	}

	private class MyAnotherClass
	{
		private Logger logger = Logger.getLogger(Thread.currentThread().getName()+"-->"+this.getClass());

		void log()
		{
			logger.debug("Where do you see this message?");
		}
	}

}

class FileAppenderFactory
{
	
	public static RollingFileAppender newInstance(RollingFileAppender fileAppender)
	{
		if(fileAppender.getName().contains("_updated"))
		{
			return fileAppender;
		}
		Layout layout = fileAppender.getLayout();
		String filename = fileAppender.getFile();
		RollingFileAppender appender;
		try
		{
			appender = new RollingFileAppender(layout, filename);
			appender.setName(fileAppender.getName());
			return appender;
		}
		catch (IOException e)
		{
			return fileAppender;
		}
	}
	
}